/**
 * Copyright (c) 2015-2030 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.app.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.yanlight.app.dal.entity.WxpayConfig;
import com.yanlight.app.request.OrderPlaceRequest;
import com.yanlight.app.response.OrderPlaceResponse;
import com.yanlight.app.service.WxpayService;
import com.yanlight.exception.ErrorType;
import com.yanlight.exception.TradeException;
import com.yanlight.app.response.OrderWxpayPlaceResponse;
import com.yanlight.support.wx.WxConstants;
import com.yanlight.support.wx.model.WxJsPaySign;
import com.yanlight.support.wx.model.WxOrder;
import com.yanlight.support.wx.request.WxOrderRequest;
import com.yanlight.support.wx.util.WxUtil;
import com.yanlight.type.StatusType;
import com.yanlight.app.dal.dao.WxpayConfigDAO;
import com.yanlight.util.JedisUtil;
import com.yanlight.util.ToolsUtil;

/**
 * 
 * @author haolw
 * @time 2017/12/07
 */
@Service
public class WxpayServiceImpl implements WxpayService {
	private final String WXPAY_CONFIG_KEY_PREFIX = "trade_wxpay_config_";
	@Autowired
	private WxpayConfigDAO wxpayConfigDAO;

	public WxpayConfig findConfig(Integer companyId) {
		WxpayConfig config = null;
		String key = getWxpayConfigKey(companyId);
		Boolean exists = JedisUtil.exists(key);
		if (!exists) {
			config = wxpayConfigDAO.findByCompanyId(companyId);
			if (config != null) {
				JedisUtil.set(key, config);
			}
		} else {
			config = JedisUtil.get(key, WxpayConfig.class);
		}
		return config;
	}

	@Override
	public boolean checkConfig(Integer companyId) {
		WxpayConfig config = findConfig(companyId);
		if (config == null) {
			return false;
		}
		if (config.getStatus().equals(StatusType.UNACTIVITY.ordinal())) {
			return false;
		}
		if (StringUtils.isEmpty(config.getMchId())) {
			return false;
		}
		return true;
	}

	@Override
	public boolean validate(OrderPlaceRequest request) {
		Integer companyId = request.getCompanyId();
		String buyerId = request.getBuyerId();
		String fromFee = request.getTotalFee();
		if (companyId == null) {
			throw TradeException.error(ErrorType.NO_OPEN_SERVICE);
		}
		if (StringUtils.isBlank(fromFee)) {
			throw TradeException.error(ErrorType.INCOMPLETE_PARAMETERS);
		}
		if (StringUtils.isBlank(buyerId)) {
			throw TradeException.error(ErrorType.INCOMPLETE_PARAMETERS);
		}
		WxpayConfig config = findConfig(companyId);
		if (config == null) {
			throw TradeException.error(ErrorType.NO_OPEN_SERVICE);
		}
		String mchId = config.getMchId();
		if (StringUtils.isBlank(mchId)) {
			throw TradeException.error(ErrorType.NO_OPEN_SERVICE);
		}
		return true;
	}

	@Override
	public String getMchUserId(Integer companyId) {
		WxpayConfig config = findConfig(companyId);
		if (config == null) {
			return null;
		}
		return config.getMchId();
	}

	@Override
	public OrderPlaceResponse placeOrder(OrderPlaceRequest request) {
		Integer companyId = request.getCompanyId();
		String fromFee = request.getTotalFee();
		String sn = request.getSn();
		WxpayConfig wxpayConfig = findConfig(companyId);
		String appId = WxConstants.appId;
		String mchId = WxConstants.mchId;
		String mchKey = WxConstants.apiKey;
		String subMchId = wxpayConfig.getMchId();
		String limitPay = wxpayConfig.getLimitPay();
		String outTradeNo = request.getOutTradeNo();
		Integer totalFee = ToolsUtil.convertFee(NumberUtils.createDouble(fromFee));
		String spbillCreateIp = request.getSpbillCreateIp();
		String openid = request.getBuyerId();
		String notifyUrl = WxConstants.getNotifyUrl(companyId);
		String companShortyName = request.getCompanyShortName();
		String body = WxConstants.getBody(companShortyName, sn);

		WxOrderRequest orderRequest = new WxOrderRequest();
		orderRequest.setAppId(appId);
		orderRequest.setMchId(mchId);
		orderRequest.setSubMchId(subMchId);
		orderRequest.setBody(body);
		orderRequest.setOutTradeNo(outTradeNo);
		orderRequest.setTotalFee(totalFee);
		orderRequest.setSpbillCreateIp(spbillCreateIp);
		orderRequest.setNotifyUrl(notifyUrl);
		orderRequest.setOpenid(openid);
		if (StringUtils.isNotBlank(limitPay)) {
			orderRequest.setLimitPay(limitPay);
		}
		String prepayId;
		try {
			WxOrder wxOrder = WxUtil.placeOrder(mchKey, orderRequest);
			if (wxOrder.success()) {
				prepayId = wxOrder.getPrepayId();
			} else {
				throw TradeException.error(ErrorType.PLACE_ORDER_FAILURE);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw TradeException.error(ErrorType.PLACE_ORDER_FAILURE);
		}
		WxJsPaySign jsPaySign = WxUtil.jsPaySign(appId, mchKey, prepayId);
		OrderWxpayPlaceResponse response = new OrderWxpayPlaceResponse();
		response.setAppId(appId);
		response.setNonceStr(jsPaySign.getNonceStr());
		response.setPackageStr(jsPaySign.getPackageStr());
		response.setPaySign(jsPaySign.getPaySign());
		response.setSignType(jsPaySign.getSignType());
		response.setTimeStamp(jsPaySign.getTimeStamp());
		return response;
	}

	private String getWxpayConfigKey(Integer companyId) {
		return WXPAY_CONFIG_KEY_PREFIX + companyId;
	}

}
